package com.almeros.ohos.multitouch.library;

import ohos.multimodalinput.event.TouchEvent;

import java.math.BigDecimal;

public class ScaleGestureDetector {

    private static final int INVALID_POINTER_INDEX = -1;
    private float fX, fY, sX, sY;
    private int mPointerIndex1, mPointerIndex2;
    private float mScale = 1;

    private OnScaleGestureListener mListener;
    private float tempV;

    public ScaleGestureDetector(OnScaleGestureListener listener) {
        mListener = listener;
        mPointerIndex1 = INVALID_POINTER_INDEX;
        mPointerIndex2 = INVALID_POINTER_INDEX;
    }

    public float getScale() {
        return mScale;
    }

    public boolean onTouchEvent(TouchEvent event) {
        switch (event.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                sX = event.getPointerPosition(0).getX();
                sY = event.getPointerPosition(0).getY();
                mPointerIndex1 = event.getPointerId(0);
                break;
            case TouchEvent.OTHER_POINT_DOWN:
                fX = event.getPointerPosition(0).getX();
                fY = event.getPointerPosition(0).getY();
                mPointerIndex2 = event.getPointerId(event.getIndex());
                break;
            case TouchEvent.POINT_MOVE:
                if (mPointerIndex1 != INVALID_POINTER_INDEX && mPointerIndex2 != INVALID_POINTER_INDEX
                        && event.getPointerCount() > mPointerIndex2) {

                    float nfX, nfY, nsX, nsY;

                    nsX = event.getPointerPosition(mPointerIndex1).getX();
                    nsY = event.getPointerPosition(mPointerIndex1).getY();
                    nfX = event.getPointerPosition(mPointerIndex2).getX();
                    nfY = event.getPointerPosition(mPointerIndex2).getY();
                    calculateScaleBetweenLines(nfX, nfY, nsX, nsY);
                    if (mListener != null) {
                        mListener.onScale(this);
                    }
                    BigDecimal bignum1 = new BigDecimal(fX);
                    BigDecimal bignum2 = new BigDecimal(sX);
                    BigDecimal bignum3 = new BigDecimal(fY);
                    BigDecimal bignum4 = new BigDecimal(sY);
                    BigDecimal multiply = bignum1.subtract(bignum2).multiply(bignum1.subtract(bignum2));
                    BigDecimal multiply1 = bignum3.subtract(bignum4).multiply(bignum3.subtract(bignum4));
                    tempV = multiply.add(multiply1).floatValue();
                    fX = nfX;
                    fY = nfY;
                    sX = nsX;
                    sY = nsY;
                }
                break;
            case TouchEvent.PRIMARY_POINT_UP:
                mPointerIndex1 = INVALID_POINTER_INDEX;
                break;
            case TouchEvent.OTHER_POINT_UP:
                mPointerIndex2 = INVALID_POINTER_INDEX;
                break;
        }
        return true;
    }

    private void calculateScaleBetweenLines(float sx1, float sy1, float sx2, float sy2) {
        BigDecimal bignum1 = new BigDecimal(fX);
        BigDecimal bignum2 = new BigDecimal(sX);
        BigDecimal bignum3 = new BigDecimal(fY);
        BigDecimal bignum4 = new BigDecimal(sY);
        float value = bignum1.subtract(bignum2).floatValue();
        float value2 = bignum3.subtract(bignum4).floatValue();
        float absX = Math.abs(value);
        float absY = Math.abs(value2);

        BigDecimal bignum5 = new BigDecimal(sx1);
        BigDecimal bignum6 = new BigDecimal(sx2);
        BigDecimal bignum7 = new BigDecimal(sy1);
        BigDecimal bignum8 = new BigDecimal(sy2);
        float absXt = Math.abs(bignum5.subtract(bignum6).floatValue());
        float absYt = Math.abs(bignum7.subtract(bignum8).floatValue());

        BigDecimal bn1 = new BigDecimal(value);
        BigDecimal bn2 = new BigDecimal(value2);
        BigDecimal bn3 = new BigDecimal(sqrt(tempV));
        float floatValue = bn1.multiply(bn1).add(bn2.multiply(bn2)).floatValue();
        BigDecimal bn4 = new BigDecimal(sqrt(floatValue));
        if (Math.abs(bn4.subtract(bn3).floatValue()) > 3) {

            if (absX > absXt || absY > absYt) {
                if (mScale > 0.8f) {
                    BigDecimal bignum9 = new BigDecimal(mScale);
                    BigDecimal bignum10 = new BigDecimal(0.05f);
                    mScale = bignum9.subtract(bignum10).floatValue();
                }
            }
            if (absX < absXt || absY < absYt) {
                BigDecimal bignum9 = new BigDecimal(mScale);
                BigDecimal bignum10 = new BigDecimal(0.05f);
                mScale = bignum9.add(bignum10).floatValue();
                if (mScale > 12) {
                    mScale = 12;
                }
            }
        }
    }

    private float sqrt(float value) {
        float num = 0;
        while ((num * num) <= value) {
            num += 0.1;
        }

        for (int j = 0; j < 10; j++) {
            if (num > 0){
                BigDecimal bignum1 = new BigDecimal(value);
                BigDecimal bignum2 = new BigDecimal(num);
                float floatValue = bignum1.divide(bignum2).add(bignum2).floatValue();
                num = floatValue / 2;
            }
        }
        return num;
    }

    public static class SimpleOnScaleGestureListener implements OnScaleGestureListener {

        @Override
        public boolean onScale(ScaleGestureDetector scaleDetector) {
            return false;
        }
    }

    public interface OnScaleGestureListener {

        boolean onScale(ScaleGestureDetector scaleDetector);
    }
}
